﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace PineLake.Drmwe.Encrypts.RSA
{
    /// <summary>
    /// RSA加密解密算法
    /// </summary>
    public class RSA : IRSA
    {
        /// <summary>
        /// 生成密钥
        /// </summary>
        /// <param name="PrivateKey">私钥</param>
        /// <param name="PublicKey">公钥</param>
        /// <param name="KeySize">密钥长度：512,1024,2048,4096,8192 推荐用1024 或者2048 加密解密速度安全性比较均衡</param>
        public void Generator(out string PrivateKey, out string PublicKey, int KeySize = 2048)
        {
            RSACryptoServiceProvider Rsa = new RSACryptoServiceProvider(KeySize);
            PrivateKey = Rsa.ToXmlString(true); //将RSA算法的私钥导出到字符串PrivateKey中 参数为true表示导出私钥 true 表示同时包含 RSA 公钥和私钥；false 表示仅包含公钥。
            PublicKey = Rsa.ToXmlString(false); //将RSA算法的公钥导出到字符串PublicKey中 参数为false表示不导出私钥 true 表示同时包含 RSA 公钥和私钥；false 表示仅包含公钥。
        }

        /// <summary>
        /// RSA加密 将公钥导入到RSA对象中，加密
        /// </summary>
        /// <param name="PublicKey">公钥</param>
        /// <param name="Encryptstring">待加密的字符串(字符最大长度112个字节(56个字符))</param>
        /// <returns></returns>
        public string Encrypt(string PublicKey, string Encryptstring)
        {
            byte[] PlainTextBArray;
            byte[] CypherTextBArray;
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            try
            {
                rsa.FromXmlString(PublicKey);
                PlainTextBArray = (new UnicodeEncoding()).GetBytes(GetEncryptstring(Encryptstring));
                CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
                StringBuilder Result = new StringBuilder();
                foreach (byte bt in CypherTextBArray)
                {
                    Result.Append(bt.ToString("X2"));
                }
                rsa.Clear();
                return Result.ToString();
            }
            catch
            {
                return "403";

            }
            finally
            {
                rsa.Dispose();
            }
        }
        /// <summary>
        /// 返回少于 56个字符的长度
        /// </summary>
        /// <param name="Encryptstring"></param>
        /// <returns></returns>
        private String GetEncryptstring(String Encryptstring)
        {
            int Len = Encryptstring.Trim().Length;
            String EncryptStr = Encryptstring;
            if (Len <= 56)
            {
                return EncryptStr;
            }
            else
            {
                return EncryptStr.Substring(0, 56);
            }
        }
        /// <summary>
        /// RSA解密 将私钥导入RSA中，解密
        /// </summary>
        /// <param name="PrivateKey">私钥</param>
        /// <param name="Decryptstring">待解密的字符串</param>
        /// <returns></returns>
        public string Decrypt(string PrivateKey, string Decryptstring)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            try
            {
                int len;
                len = Decryptstring.Length / 2;
                byte[] inputByteArray = new byte[len];
                int x, i;
                for (x = 0; x < len; x++)
                {
                    i = Convert.ToInt32(Decryptstring.Substring(x * 2, 2), 16);
                    inputByteArray[x] = (byte)i;
                }
                byte[] PlainTextBArray;
                byte[] DypherTextBArray;
                string Result;

                rsa.FromXmlString(PrivateKey);
                PlainTextBArray = inputByteArray;
                DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
                Result = (new UnicodeEncoding()).GetString(DypherTextBArray);
                rsa.Clear();
                return Result;
            }
            catch
            {
                return "403";
            }
            finally
            {
                rsa.Dispose();
            }
        }
    }
}
